2024-04 の TC39 meeting
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
o[p] = f() という式は実装と仕様で評価順が異なっている。
まず単純な = の場合。右辺、そして左辺のプロパティキーの順番で実行される。
code: js
var o = {};
var p = { toString() { print('p'); return 3; } };
var f = () => { print('f'); return 4; };
code: result
#### JavaScriptCore, SpiderMonkey, V8
f
p
プロパティーキーの中に函数があった場合は
code: js
var o = {};
var p = { toString() { print('p'); return 3; } };
var f = () => { print('f'); return 4; };
var pf = () => { print('pf'); return p; };
code: result
#### JavaScriptCore, SpiderMonkey, V8
pf
f
p
とまず左辺のプロパティキーの中身、そして右辺、左辺のプロパティキーの順に実行されている。
ここで最後の行を = から += にすると
code: js
var o = {};
var p = { toString() { print('p'); return 3; } };
var f = () => { print('f'); return 4; };
var pf = () => { print('pf'); return p; };
code: result
#### V8
pf
p
f
p
#### SpiderMonkey
pf
p
f
#### JavaScriptCore
<omitted; we currently match V8 but will match SM soon>
とブラウザごとに異なる実行順となっていが、概ね左辺、右辺の順に実行される。
さて立ち返って = であっても += であっても仕様上は左辺、右辺の順に解決されるべきだが、エンジンによる実装は場合によって順番が変わっている。どのエンジンも仕様通りでない。
方針としては Web Reality に合わせるために、仕様を実装に合わせる。+= でエンジンごとに微妙に異なる部分については SpiderMonkey に合わせて V8/JavaScriptCore を修正することになった。
Stage 4 (ES2025)
Stage 4 になった 🎉
Stage 4 になった 🎉
Stage 3
また細かい Normative Change があった。
今回の会議の数日後に Temporal.Calendar と Temporal.TimeZone クラスをやめて、単なる文字列で表現するという大きな Normative Change の話が出ていて、そちらの成り行きのほうが気になる。
個人的にはカスタムカレンダー、タイムゾーンはやり過ぎだし、Intl.Locale が文字列で扱っていることからこの Normative Change は妥当だと考える(どうやら実装が複雑なため辞めたいというのが発端のようだ)。一方で既にカスタムカレンダーパッケージが存在していることもあり、ユースケースがある。すぐに解決しない話題になりそう。 eval/new Function changes for Trusted Types as Normative PR or Stage 3 (PR, slides) | Nicolò Ribaudo Trusted Types の TrustedScript のために eval や new Function にオブジェクトを入れたときの仕様を修正する提案。
Trusted Types に全情報を渡すという方針で Stage 3 になった。ただし new Function には全文字列を渡さない。
仕様を単純化するために [[VarNames]] を廃止し、eval で変数を作ったときに変数名が被るのを判定する処理をなくす提案。
前回の会議で Stage 2 になり、今回 Stage 3 になった。
Stage 2.7
Stage 2.7 になった。
Math.sumPrecise として Stage 2.7 になった。
Stage 2
[[DisposableResourceStack]] を後処理で空リストにし忘れているのが直され、文法的に export 後に using, await using が使えてしまえていたのが直された。また await using を同期的な Disposable に使用した場合に同期的に throw されないようにする修正がされた(Async Functions なのに同期 throw してしまっていた)。
さらに await using 宣言で複数の変数を作るときに、右辺が null/undefined の場合は無駄にマイクロタスクを作らないようにする Normative Change が議論された。
code: js
{
// 今の仕様では3回マイクロタスクを作るが、1回にまとめられる
}
これについてはコンセンサスが得られたが PR は修正するらしい。
Iterator を並列に結合する Iterator.prototype.zipTo{Arrays, Objects} の提案。
Array にも同じものがあっていいのではという話になっている。議論としては継続するが、特にこれが原因でこの提案がブロックされることはないとのこと。
FinalizationRegistory や Unhandled Rejection など細かな対応がなされている。また HTML 仕様への統合作業がなされている。
Vercel や V8, Igalia などが、結構進めていきたい雰囲気があるらしい。
文字列から正規表現を組み立てるときに使う RegExp.escape の提案。
フラグについて考慮が必要とのことで Stage 2.7 にはならなかった。
import defer の提案。
そもそも主にバンドラが使われている世界でブラウザに必要なのか、Top-level await との兼ね合いはどうなのかということで Stage 2.7 にならなかった。
export from 文が書かれていたときに、それが Tree Shaking 出来るかどうかの判定ができない。エコシステム的には package.json に sideEffects: false を付けたり、/*#__PURE__*/ アノテーションを付けたり、複数ファイルに跨った静的解析をしたりしている。これを解決するために export optional を追加する提案。
code: js
export optional { default as add } from "./add.js";
export optional { divide } from "./divide.js";
export optional * as timers from "./timers.js";
この提案は一見バンドラーのみにしか影響がなく、ランタイムに必要ないように見えるが Deffered Import を考慮すると意味があるらしい。そのため仕様に入れたいという話になっている。
別提案として Stage 2 になった。
Iterator.range の提案。Stage 2.7 にならなかった。
Immutable Data Structure を扱う Record & Tuple の今後の方針を考える。
=== についてのパフォーマンスの問題は Jxck さんのスライドが詳しい。
プリミティブでは厳しかったのでオブジェクトにしてしまって === では同一の値であっても一致しないが、Record.equal や Set の中身での比較など、別の方法で比較するので十分なのではないかという議論があったが、賛否両論だった。
https://gyazo.com/75e526b682519c4a94e107c7be12436f
テンプレートリテラルの Tag Functions にやってくる引数として作られた配列かどうかを判定する函数を追加する提案。
Realm 独立な仕様にするかどうかで議論があった。今の内部スロットを使う仕様だと Cross-Realm でやってきた配列に対しても true を返すため、(提案がブロックされるほど大きい訳ではないが)安全性の懸念がある。
Stage 1
最適化のために Atomics.microwait(spins); を追加する提案。
Stage 2 にはならなかった。
ES Modules で Web Worker に突っ込めるようにする提案。
Module Harmony として、もともとは import module (Module Instance Phase Import) という新しいフェーズを追加する提案だったが、Stage 3 の import source (Source Phase Import) と同じレイヤーにすることが決まった。
https://gyazo.com/0b3e572737d5cd9ac1e24e9eeb530c09
これによりモジュール式とモジュール宣言も影響を受けるはず。
Top-level await を使った非同期モジュールが含まれていないことをアサートする機能の提案。
"assert sync"; ディレクティブを追加する方針になったようだ。
ブラウザ的にはあまりモチベーションがなさそうで Stage 2 にはならなかった。
MessageFormat 2.0 を使うかどうか議論されていたが、その方針で進めることになった。
1回の評価で確定しないカバー文法の懸念があり、Stage 2 にはならなかった。
カバー文法については uhyo さんの記事が詳しい。
void ではなくて _ の方がいいかもしれないという話が出ている。
方針としてはいいがこれもカバー文法的な問題があるため、それが解決されるまで Stage 2 にはならない。
IEEE 754 Decimal128 を扱うクラスを追加する提案。末尾の 0 の正規化処理をどうするかが議論されている。例えば 1.2 と 1.20 を比較したときに
常に正規化処理をすることで 1.20 は 1.2 として扱う
すべての桁をそのまま保持する
の2パターンが考えられる。
Stage 2 にはならなかった。とりあえず今後はオフラインで作業されるとのこと。
SharedArrayBuffer に似ているが、シリアライズされたオブジェクトとして扱うことで最適化する Shared Structs を追加する提案。
メソッドの扱いについて議論されている。
bringing back Error.isError, for stage 1 or 2 (or even 2.7) | Jordan Harband かつて withdrown された Error.isError を再度追加する提案。
再登場の理由としては以前は Object#toString によるチェックで十分とされていたが Symbol.toStringTag の登場によりその信頼性がなくなっていること、また Map など他のクラスと違い Error のみ内部スロット( [[ErrorData]])による判定をするプロトタイプメソッドはないことから Error.isError があることが望まれるということらしい。
個人的に DOMException がどうなるのかが気になる。
Stage 1 になった。
現状 Stage 3 Explicit Resource Management では直接使うオブジェクト自身が Symbol.dispose/Symbol.asyncDispose メソッドを必要としている。
Iterable に対する Iterator と同じように Symbol.enter が実装されているオブジェクトに using や DisposableStack#use を使った場合に Symbol.dispose/Symbol.asyncDispose するオブジェクトを別で用意できるようにする提案。
code: js
function getStrictResource() {
// Construct the actual resource.
const actualResource = {
value: "resource",
};
// Construct and return a resource wrapper that imposes strict enforcement semantics.
return {
return actualResource;
}
};
}
{
using res = getStrictResource(); // retvalSymbol.enter() is invoked. res.value; // "resource"
Stage 1 になった。
Signals for Stage 1 (slides) | Daniel Ehrenberg and Jatin Ramanathan Preact や Vue.js の Signals を仕様に入れる提案。
Stage 1 になった。
Stage 0
N/A
Withdrown
“array last” proposal withdrawn | Jordan Harband Array#last{Item, Index} の提案。ES2022 Array#at や Stage 1 Slice Notation で事足りるとして withdrawn になった。
その他
TC39 website - call for translators - issue | Chris de Almeida 公式サイトの翻訳が足りていない部分がまとめられている。
Stop coercing things pt 4 (slides) | Kevin Gibbons 今後の提案でプリミティブ間の変換(boolean に変換するのを除く)、一部を除いてプリミティブからオブジェクトへの変換を辞める話。
総括
ES2024 がフリーズされ、今回から ES2025 の策定となる。早速 Set Methods が Stage 4 となった。
Temporal に大きな変更が入りそうなので、まだしばらく策定が長引きそうなのが気がかり。個人的には Record & Tuple と import source も進んでほしい。
新しい提案としては Signals がどうなっていくのか気になる。